﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NCrontab;
using ScheduledTasks;
using SqlSugar;
using System.Collections.Concurrent;

public class TaskService : BackgroundService
{
    private readonly ILogger<TaskService> _logger;
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly ConcurrentDictionary<string, CrontabSchedule> _schedules = new();
    private readonly ConcurrentDictionary<string, DateTime> _nextOccurrences = new();

    public TaskService(
        ILogger<TaskService> logger,
        IServiceScopeFactory scopeFactory)
    {
        _logger = logger;
        _scopeFactory = scopeFactory;

        // 初始化任务调度信息（不直接存储任务实例）
        using (var scope = _scopeFactory.CreateScope())
        {
            var tasks = scope.ServiceProvider.GetServices<IScheduledTask>();
            foreach (var task in tasks)
            {
                var options = new CrontabSchedule.ParseOptions { IncludingSeconds = true };
                _schedules.TryAdd(task.GetType().FullName!, CrontabSchedule.Parse(task.Schedule, options));
                _nextOccurrences.TryAdd(task.GetType().FullName!,
                    _schedules[task.GetType().FullName!].GetNextOccurrence(DateTime.Now));
            }
        }
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("定时任务服务已启动");

        while (!stoppingToken.IsCancellationRequested)
        {
            var now = DateTime.Now;

            // 遍历任务类型，而不是任务实例
            foreach (var taskType in _schedules.Keys)
            {
                if (_nextOccurrences[taskType] <= now)
                {
                    try
                    {
                        _logger.LogInformation($"开始执行任务: {taskType}");

                        // 在每次执行时创建新作用域并解析任务
                        using (var scope = _scopeFactory.CreateScope())
                        {
                            var tasks = scope.ServiceProvider.GetServices<IScheduledTask>();
                            var task = tasks.FirstOrDefault(t => t.GetType().FullName == taskType);

                            if (task != null)
                            {
                                var db = scope.ServiceProvider.GetRequiredService<SqlSugarClient>();
                                await task.ExecuteAsync(db);

                                // 更新下一次执行时间
                                _nextOccurrences[taskType] =
                                    _schedules[taskType].GetNextOccurrence(DateTime.Now);

                                _logger.LogInformation($"任务 {taskType} 执行完成，下次执行时间: {_nextOccurrences[taskType]}");
                            }
                            else
                            {
                                _logger.LogWarning($"找不到任务类型: {taskType}");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, $"任务 {taskType} 执行失败");
                    }
                }
            }

            await Task.Delay(1000, stoppingToken);
        }

        _logger.LogInformation("定时任务服务已停止");
    }
}